const { WebElement, until } = require("selenium-webdriver");
const Browser = require("./Browser")

class Element {
    constructor(webElement = WebElement.prototype, browser = Browser.prototype) {
        this.webElement = webElement;
        this.browser = browser;
    }

    async input(...args) {
        await this.webElement.sendKeys(...args);
        this.takeScreenshot();
    }

    async click() {
        try {
            await this._click(false);
        } catch (error) {
            await this.browser.webDriver.sleep(100);
            await this._click(true);
        }
    }

    async _click(jsMode = false) {
        if (jsMode) {
            await this.browser.webDriver.executeScript("arguments[0].click()", this.webElement);
        } else {
            await this.webElement.click();
        }
        this.takeScreenshot();
    }

    async clear() {
        await this.webElement.clear();
        this.takeScreenshot();
    }

    async doubleClick() {
        let script = `let event = document.createEvent('MouseEvents');
        event.initEvent('dblclick', true, true);
        arguments[0].dispatchEvent(event);`
        await this.browser.webDriver.executeScript(script, this.webElement);
        this.takeScreenshot();
    }

    async contextClick() {
        let actions = this.browser.webDriver.actions();
        actions.contextClick(this.webElement)
        await actions.perform();
    }

    async getText(jsMode = false) {
        if (jsMode) {
            let text = await this.browser.webDriver.executeScript("return arguments[0].innerText || arguments[0].textContent", this.webElement);
            return text;
        }
        return await this.webElement.getText()
    }

    async getAttribute(attributeName) {
        return await this.webElement.getAttribute(attributeName);
    }

    async getValue() {
        return await this.browser.webDriver.executeScript("return arguments[0].value", this.webElement);
    }

    async isDisplayed() {
        return await this.webElement.isDisplayed();
    }

    async isSelected() {
        return await this.webElement.isSelected();
    }

    async isEnabled() {
        return await this.webElement.isEnabled();
    }

    async waitUntilBeEnabled() {
        await this.browser.webDriver.wait(until.elementIsEnabled(this.webElement), this.browser.config.timeout);
    }

    async waitUntilBeDisabled() {
        await this.browser.webDriver.wait(until.elementIsDisabled(this.webElement), this.browser.config.timeout);
    }

    async scrollIntoView() {
        let script = "arguments[0].scrollIntoView()"
        await this.browser.webDriver.executeScript(script, this.webElement);
    }

    takeScreenshot() {
        if (this.browser.config.screenshot.isEnabled) {
            this.browser.takeScreenshot();
        }
    }

}

module.exports = Element;